package cn.enjoy.design.structure.proxy.manager;


import cn.enjoy.design.structure.proxy.event.FlowEvent;
import cn.enjoy.design.structure.proxy.listener.FlowStateAsyncListener;
import cn.enjoy.design.structure.proxy.listener.FlowStateListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ResolvableType;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @author K
 * @date 2021-07-18 16:50
 */
@Slf4j
public class FlowStateManager {

    private final Set<FlowStateListener<? extends FlowEvent>> listeners = new HashSet<>();

    private final ExecutorService observerExecutor = Executors
            .newFixedThreadPool(Runtime.getRuntime().availableProcessors() / 2);


    /**
     * 注册监听器
     *
     * @param listener 监听器
     */
    public void register(FlowStateListener<?> listener) {
        listeners.add(listener);
    }

    /**
     * 发布事件
     *
     * @param flowEvent 事件
     */
    public void publish(FlowEvent flowEvent) {
        publish(null, flowEvent);
    }

    public void publish(Runnable function, FlowEvent flowEvent) {
        List<FlowStateListener> ableListener = findAbleListener(flowEvent);
        for (FlowStateListener listener : ableListener) {
            if (listener instanceof FlowStateAsyncListener) {
                observerExecutor.execute(() -> {
                    try {
                        listener.handler(flowEvent);
                    } catch (Throwable e) {
                        log.error("flow state listener exec handler is error", e);
                    }
                });
            } else {
                listener.handler(flowEvent);
            }
        }
        if (function != null) function.run();
    }

    private List<FlowStateListener> findAbleListener(FlowEvent flowEvent) {
        // 1. 当前事件类 例如：BaseSubmitEvent事件得到 BaseSubmitEvent.class
        Class<? extends FlowEvent> flowEventClass = flowEvent.getClass();
        // 2. 匹配所有Listener泛型等于当前事件类的Listener
        return listeners.stream().filter(x -> {
//            2.1 找到当前listener的泛型类 例如：BaseFlowFormListener的泛型类是 FlowEvent

            // TODO 方式一 Java原生获取泛型 有点问题
//            ParameterizedType parameterizedType = (ParameterizedType) x.getClass().getGenericSuperclass();
//            Type type = parameterizedType.getActualTypeArguments()[0];

            // TODO 方式二 Spring提供获取泛型
//            ResolvableType resolvableType = ResolvableType.forClass(x.getClass());
//            ResolvableType superType = resolvableType.getSuperType();
//            Class<?> resolve = resolvableType.getSuperType().getGeneric(0).resolve();
//            Class<?> resolve1 = resolvableType.getGeneric(0).resolve();
//            Class<?>[] classes1 = resolvableType.resolveGenerics();

            Class<?>[] classes = ResolvableType.forClass(x.getClass()).as(FlowStateListener.class).resolveGenerics();
            for (Class<?> clazz : classes) {
                if (clazz.equals(FlowEvent.class)) {
                    return true;
                } else if (clazz.equals(flowEventClass)) {
                    return true;
                } else if (flowEventClass.getGenericSuperclass() != null && flowEventClass.getGenericSuperclass().equals(clazz)) {
                    // 事件类的父类 例如：BaseSubmitEvent的父类是 BaseFlowFormEvent
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());
    }

}